#include "m1test.h"

U32 APP_M1Card_ReadPublish( void );
void APP_WriteRec_M1Rec( U32 id, U32 recstat, U32 stat );

U32 Card_M1_Check( void )
{
	U32 rcode;
	U08 combuf[32];

	rcode = APP_M1Card_ReadPublish( );					//获取发行区信息
	if( rcode != 0 )
	{ 
		DEF_SysCard_Debug;
		return 1;
	}
	//读钱包信息区
	rcode = AH_M1Card_ReadCardWallet( &TradeInformation.OldPurseBalance, combuf );
	if( rcode != 0 )
	{ 
		DEF_SysCard_Debug;
		return 1;
	}
	
	TradeInformation.Mtype = 3;//天磁老卡，主卡类型
	
	CurCalc_DataCpy( M1_CommInfo.ComBuf, combuf, 16 ); 						//公共信息区内容 暂存


	return 0;
}

U32 ICF_MiOne_GetPsamTAC( U08 *pdata, U32 size, U08 *ptac )
{
 	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x1A;	//INS
	gCmdBuffer[2] = 0x26;	//P1 PSAM密钥用途号 08
	gCmdBuffer[3] = 0x01;	//P2 //gCardInfo.PsamPasWodVer;	//PSAM密钥版本号
	gCmdBuffer[4] = 0x08;	//Lc	//临时秘钥分散系数长度

	memcpy( &gCmdBuffer[5], M1_Publish.CityID, 2 );//城市代码
	memset( &gCmdBuffer[7], 0xFF, 6 );

	rcode = ICC_APDU_Exchange( Gich_Sam, gCmdBuffer, (5+8), gpRcvBuffer, &Grcv_Len, ICC_APUD_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )	  	//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	if( rcode != 0x9000 )
	{ return rcode; }
	
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0xFA;	//INS
	gCmdBuffer[2] = 0x05;	//P1,
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = size;	
	memcpy( gCmdBuffer+5, pdata, size );

	rcode = ICC_APDU_Exchange( Gich_Sam, gCmdBuffer, (size+0x05), gpRcvBuffer, &Grcv_Len, ICC_APUD_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )	  	//长度判断
	{ return 3;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	if( rcode != 0x9000 )
	{ return rcode;	}

   memcpy( ptac, gpRcvBuffer, 4 );
   return rcode;
}

U32 Card_M1_Exch( void )
{
	U32	rcode;
	U08 combuf[32];
	U08 recbuf[16];

	printf("Card_M1_Exch:\n");
//	U08 buf[20];
	memcpy( TradeInformation.LastCardPhySN, TradeInformation.CardPhySN, 12 );//暂存卡号
	
/*
***************************************************************************************************
*〖1〗钱包扣钱
***************************************************************************************************
*/
	//公共信息区组帧
	CurCalc_DataCpy( combuf, M1_CommInfo.ComBuf, 16 ); 						//公共信息区内容
	
	CurCalc_DataCpy( recbuf, &TradeInformation.DealTime[2], 4 ); 			//时间
	recbuf[4]  = ( TradeInformation.OldPurseBalance >> 24 );
	recbuf[5]  = ( TradeInformation.OldPurseBalance >> 16 );				
	recbuf[6]  = ( TradeInformation.OldPurseBalance >>  8 );
	recbuf[7]  = ( TradeInformation.OldPurseBalance >>  0 ); 				//交易前余额
	recbuf[8]  = ( TradeInformation.DealMoney >> 16 );
	recbuf[9]  = ( TradeInformation.DealMoney >>  8 );
	recbuf[10] = ( TradeInformation.DealMoney >>  0 );						//交易金额
	recbuf[11] = TradeInformation.CardpPE[3];								//交易类型
	CurCalc_DataCpy( &recbuf[12], &gSamAppInfo.PsamTID[2], 4 ); 			//机具号 ??
	switch( TradeInformation.CardpPE[3] )
	{
		case 1://钱包
			combuf[8]  = 0x10;
			recbuf[11] = 0x01;//消费记录类型,01钱包，02次卡
			rcode = AH_M1Card_WriteCardWallet( TradeInformation.DealMoney, 
											   &TradeInformation.NewPurseBalance, 
											   combuf, 
											   recbuf );
			break;
		case 3://次卡
			combuf[8]  = 0x11;
			recbuf[11] = 0x02;
			rcode = AH_M1Card_WriteCardNumWallet( TradeInformation.DealMoney, 
											   &TradeInformation.NewPurseBalance, 
											   combuf, 
											   recbuf );
			break;
		default :return 1;
	}
	if( rcode != 0 )	
	{ 
		DEF_SysCard_Debug;
		if( rcode != 13200 )
		{
		 	DEF_SysCard_Debug;
			return rcode; 			
		}
	}
	else
	{ CurCalc_DataCpy( M1_CommInfo.ComBuf, combuf, 16 ); }					//公共信息内容

/*
***************************************************************************************************
*〖2〗保存交易记录，提示成功信息
***************************************************************************************************
*/
	TradeInformation.TTC[0] = ( OthCfg.M1SamDealCout >> 24 ) & 0xFF;
	TradeInformation.TTC[1] = ( OthCfg.M1SamDealCout >> 16 ) & 0xFF;
	TradeInformation.TTC[2] = ( OthCfg.M1SamDealCout >>  8 ) & 0xFF;
	TradeInformation.TTC[3] = ( OthCfg.M1SamDealCout >>  0 ) & 0xFF;		//SAM交易流水号
	//M1卡TAC计算
	
	//8个0+交易金额(4)+交易类型(1 1=电子钱包，2=月票，3=次卡)+终端机编号PSAM(6)+交易序号(2)+交易时间YYMDHMS(7)
	memset( combuf, 0, 8 );
	combuf[8]  = ( TradeInformation.DealMoney >> 24 );
	combuf[9]  = ( TradeInformation.DealMoney >> 16 );	 
	combuf[10] = ( TradeInformation.DealMoney >>  8 );
	combuf[11] = ( TradeInformation.DealMoney >>  0 );
	//combuf[12] = TradeInformation.CardpPE[3];
	combuf[12] = 1;			   												//这里固定为1
	memcpy( &combuf[13], gSamAppInfo.PsamTID, 6 );

	switch( TradeInformation.CardpPE[3] )
	{
		case 1://钱包
			rcode = ( M1_CommInfo.ComBuf[0x02] << 8 ) | M1_CommInfo.ComBuf[0x03];
			break;
		case 2://月票
			rcode = ( M1_CommInfo.ComBuf[0x05] << 8 ) | M1_CommInfo.ComBuf[0x06];
			break;
		case 3://次卡
			rcode = ( M1_CommInfo.ComBuf[0x05] << 8 ) | M1_CommInfo.ComBuf[0x06];
			break;
	}
	rcode--;
	combuf[19] = ( rcode >> 8 );
	combuf[20] = rcode; 													//消费交易前计数器
	memcpy( ( combuf + 21 ), TradeInformation.DealTime, 7 ); 				//交易日期
	
	rcode = ICF_MiOne_GetPsamTAC( combuf, 28, TradeInformation.TAC );		//TAC计算 需要10ms左右时间
	if( rcode != 0x9000 )
	{ APP_WriteRec_M1Rec( DEF_RecMoryBank_Black01, 3, 0 ); }				//TAC错误
	else
	{ APP_WriteRec_M1Rec( DEF_RecMoryBank_Black01, 1, 0 ); }				//保存交易记录
	
//==============>>显示语音提示
	if( TradeInformation.CardpPE[3] == 3 )									//次卡钱包
	{ OthCfg.MotoCardNumCout++;	}											//司机卡当班次汇总
	else
	{
		OthCfg.MotoCardRecCout++;											//司机卡当班记录总数
		OthCfg.MotoCardRecMone += TradeInformation.DealMoney;		
	}
	OthCfg.M1SamDealCout++;	   												//模拟CPU消费的SAM卡交易流水号，每消费一次加1
	APP_Save_OthCfg( 0 );				

	if( TradeInformation.CardpPE[3] != 1 )
	{ TradeInformation.NewPurseBalance = ( TradeInformation.CurOldPurseBalance - TradeInformation.DealMoney ); }
																			//只显示当月有效的
    printf("OK,consume success!\r\n");

	return 0;
}
U32 Card_M1_WaitInBusinessMoney( void )
{
	U32 i;
	
	//===================>正常票价折扣处理
	for( i = 0; i < DealCfg.CardTypeCout; i++ )			//查找票价
	{
		if( DealCfg.DiscInfo[i].CardType == M1_Publish.CardType )
		{ break; }
	}
	if( i >= DealCfg.CardTypeCout )
	{
		DEF_SysCard_Debug;
		return 1;			  
	}
	TradeInformation.CardTypeCout = i;					//记下票价类型位置
	
	if( ( DealCfg.DiscInfo[TradeInformation.CardTypeCout].CardStat & 0x8000 ) == 0 )
	{											  		//禁止此类卡交易
		DEF_SysCard_Debug;
		return 1;
	}
	if( TradeInformation.CardpPE[3] == 1 ) 	
	{ 
		TradeInformation.DealMoney = ( ( TradeInformation.UnitPrice * DealCfg.DiscInfo[TradeInformation.CardTypeCout].PurseDisc ) / 100 ); 
		if( TradeInformation.DealMoney > TradeInformation.OldPurseBalance )
		{
			DEF_SysCard_Debug;
		    return 1;
		}
	}
	else if( TradeInformation.CardpPE[3] == 3 )	  
	{	 					
		TradeInformation.DealMoney = 1;
	}
	else
	{ 		
		TradeInformation.DealMoney = ( ( TradeInformation.UnitPrice * DealCfg.DiscInfo[TradeInformation.CardTypeCout].MonthDisc ) / 100 ); 
	}
	return 0;
}


U32 APP_M1Card_ReadPublish( void )
{
	U32 rcode;
	U08 buf[48];
	U08 buf2[8];
	
	printf("APP_M1Card_ReadPublish:\n");
	rcode = ICC_MiOne_GetPhySn(TradeInformation.CardPhySN);//必需要先调用此函数获取物理号
	if( rcode != 0 )
	{ 
		DEF_SysCard_Debug;	
	    return rcode; 
	}
	rcode = AH_M1Card_ReadPublish( TradeInformation.CardPhySN,buf,0 );
	if( rcode != 0 )
	{ 
		DEF_SysCard_Debug;	
		return rcode;	
	}
//===================>>启用标记

	memcpy( buf2, &buf[16+8], 4 );	//启用期
	if( memcmp( buf2, TradeInformation.DealTime, 4 ) > 0 )
	{
		DEF_SysCard_Debug;	
		return 1;	
	}

	memcpy( buf2, &buf[16+4], 4 ); //停用期
	if( memcmp( buf2, TradeInformation.DealTime, 4 ) < 0 )
	{		
		DEF_SysCard_Debug;	
		return 1;	
	}

	CurCalc_DataCpy( M1_Publish.CityID, &buf[0], 2 );
	CurCalc_DataCpy( M1_Publish.CallingID, &buf[2], 2 );
	CurCalc_DataCpy( M1_Publish.PublishSN, &buf[4], 4 );
	CurCalc_DataCpy( M1_Publish.CardTAC, &buf[8], 4 );
	M1_Publish.CardEnableSign = buf[12];
	M1_Publish.CardType = buf[13];		 

	CurCalc_DataCpy( TradeInformation.CityCode, M1_Publish.CityID, 2 );
	
	CurCalc_DataCpy( TradeInformation.CardASN, buf, 8 );//分别为:城市代码+行业代码+发行流水号 
		
	printf("ok!\n");
	return 0;	
}


void APP_WriteRec_M1Rec( U32 id, U32 recstat, U32 stat )
{
	U32 rcode,recsn,pyhsn,i;
	U08 buf[DEF_FLASH_MaxRecLength];							//这里有问题的

	memset( buf, 0, DEF_FLASH_MaxRecLength );					//将所有缓冲区写全0
//=====================================>> 记录组帧
	rcode = APP_Get_RecFileNO( id, &pyhsn, &recsn );			//获取最后一条记录的流水号错误，
	if( rcode != 0 ) 											//写记录失败，失败处理
	{ DEF_SysCard_Debug; }
	pyhsn++;
	buf[0] = ( pyhsn >> 24 );
	buf[1] = ( pyhsn >> 16 );
	buf[2] = ( pyhsn >> 8 );
	buf[3] = pyhsn;												//记录的前4字节存储记录流水号

	buf[4] = DEF_RecType_Trade;									//记录类型 消费记录

	memcpy( &buf[5], gSamAppInfo.PsamTID, 6 );					//POS编号
	memcpy( &buf[11], DealCfg.CircuitryID, 2 );					//线路标识
	memcpy( &buf[13], TradeInformation.DealTime, 7 );			//交易时间
	memcpy( &buf[20], buf, 4 );									//记录流水号

	if( stat != 0 ) 		//分段收费逃票
	{ memcpy( &buf[24], CPUM1_BillInfo.MotoEmpID, 3 ); }
	else
	{ memcpy( &buf[24], OthCfg.MotoEmpID, 3 ); }				//司机卡empID

	memcpy( &buf[27], M1_CommInfo.CounterSn, 4 );  			//用户帐号
	
	memcpy( &buf[31], TradeInformation.CardASN, 8 );  			//卡应用序列号
	
	buf[39] = M1_Publish.HolderCardSn;						//持卡序号
	
	buf[40] = 1;												//卡类别 1 M1卡，2 CPU卡
	memcpy( &buf[41], SysCfg.AppCityID, 2 );					//交易地城市代码
	memcpy( &buf[43], TradeInformation.CityCode, 2 );			//卡所属地城市代码

	switch( TradeInformation.CardpPE[3] )
	{
		case 1://钱包
			i = ( M1_CommInfo.ComBuf[0x01] << 8 ) | M1_CommInfo.ComBuf[0x02];
			break;
		case 2://月票
			i = ( M1_CommInfo.ComBuf[0x04] << 8 ) | M1_CommInfo.ComBuf[0x05];
			break;
		case 3://次卡
			i = ( M1_CommInfo.ComBuf[0x0D] << 8 ) | M1_CommInfo.ComBuf[0x0E];
			break;
	}
	if( recstat != 2 )											//灰记录里，交易计数是没有加的
	{ i--; }
	buf[45] = ( i >> 8 );
	buf[46] = i; 												//消费交易前计数器

	buf[47] = ( TradeInformation.OldPurseBalance >> 24 );		//用户卡交易前余额
	buf[48] = ( TradeInformation.OldPurseBalance >> 16 );
	buf[49] = ( TradeInformation.OldPurseBalance >>  8 );
	buf[50] = ( TradeInformation.OldPurseBalance >>  0 );

	buf[51] = ( TradeInformation.DealMoney >> 8 );				//用户卡交易金额
	buf[52] = ( TradeInformation.DealMoney >> 0 );

	if( ( DealCfg.TimePriceStat != 0 ) || ( stat != 0 ) )		//分段收费模式
	{ buf[53] = 0x40; }
	else
	{ buf[53] = 0x00; }//交易应用类型（测试标记）

	buf[54] = ( ( TradeInformation.CardpPE[3] << 3 ) | ( recstat & 0x03 ) );
																//钱包类型,记录类型状态
	memcpy( &buf[55], TradeInformation.TTC, 4 );				//SAM交易流水号
	
	{ buf[59] = 0; }

	buf[60] = M1_Publish.CardType;
													   			//子卡类型 普通卡，老人卡等
	buf[61] = 0;												//卡内版本，没有使用写0
	buf[62] = 0x01;												//交易性质,公交，地铁等

	if( ( TradeInformation.CardpPE[3] == 3 ) || ( stat != 0 ) )	//次卡折扣金额为0
	{ 															//逃票记录没有折扣
		buf[63] = 0;
		buf[64] = 0;
	}
	else
	{
		i = 0;
		if( TradeInformation.UnitPrice > TradeInformation.DealMoney )
		{ i = TradeInformation.UnitPrice - TradeInformation.DealMoney; }
		buf[63] = ( i >> 8 );
		buf[64] = i;						  					//折扣金额
	}

	if( ( DealCfg.TimePriceStat != 0 ) || ( stat != 0 ) )		//分段收费模式
	{
//		buf[63] = 0;
//		buf[64] = 0;											//分段收费模式，折扣金额为0
		
		if( stat != 0 )	
		{ memcpy( &buf[65], CPUM1_BillInfo.PsamTID, 6 ); }		//逃票POS编号	
		else
		{ memset( &buf[65], 0, 6 ); }	   						//正常
		
		buf[71] = CPUM1_BillInfo.UpID >> 8;						//上车站点编号
		buf[72] = CPUM1_BillInfo.UpID;							//上车站点编号
		if( stat != 0 )											//逃票情况没有下车站点编号
		{
			buf[73] = 0;										//下车站点编号
			buf[74] = 0;										//下车站点编号
		}
		else
		{
			buf[73] = ( 0 >> 8 );				//下车站点编号
			buf[74] = 0;						//下车站点编号
		}
	}
	else
	{
		memset( &buf[65], 0, 6 );								//逃票POS编号		
		memset( &buf[71], 0, 2 );								//上车站点编号
		memset( &buf[73], 0, 2 );								//下车站点编号		
	}

	if( recstat == 2 )											//灰记录TAC为0
	{ memset( TradeInformation.TAC, 0, 4 ); }
	memcpy( &buf[75], TradeInformation.TAC, 4 );				//TAC码

//=====================================>> 保存记录
	rcode = APP_Write_RecFile( id, buf );						//保存记录
	if( rcode != 0 )
	{
		DEF_SysCard_Debug;	
	}
	else
	{
		printf("APP_Write_RecFile OK\n");
	}
}


void testcard_m1( void )
{
	
	U32 rcode = 0;
	printf("begin m1 card test:\n");
	get_time();
	//PSAM
	//App_PSAM_Init();

	rcode = Card_M1_Check();
	if( rcode != 0 )												
	{ goto END; }
	printf("card check oK!\n");
	TradeInformation.CardpPE[3] = 1;
    TradeInformation.DealMoney = 1;//测试扣1分
	//rcode = Card_M1_WaitInBusinessMoney();
	//if( rcode != 0 )												
	//{ goto END; }
	rcode = Card_M1_Exch();
	if( rcode != 0 )												
	{ goto END; }
    
    return;

	END:	
    printf("card test over!\n");
    
}
